package cn.xorange.commons.datasource.configuration;

import cn.xorange.commons.datasource.constants.DataDefaultConstants;
import cn.xorange.commons.exception.DataException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

/**
 * @author : yangjian
 * date : 2024/12/9
 * description :
 */
@Slf4j
@Component
public class MyBatisProperties {

    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";

    @Resource
    DSConfig dataSourceConfig;

    @Value("${mybatis.configuration.mapUnderscoreToCamelCase:true}")
    public boolean mapUnderscoreToCamelCase;


    @Value("${mybatis.mapperLocations:"+ DataDefaultConstants.MYBATIS_MAPPER_LOCATIONS +"}")
    //@Value("${mybatis.configuration:#{null}}")
    public String mapperLocations;


    public static String setTypeAliasesPackage(String typeAliasesPackage) {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
        List<String> allResult = new ArrayList<>();
        try {
            for (String aliasesPackage : typeAliasesPackage.split(",")) {
                List<String> result = new ArrayList<>();
                aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                        + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
                org.springframework.core.io.Resource[] resources = resolver.getResources(aliasesPackage);
                if (resources != null && resources.length > 0) {
                    MetadataReader metadataReader = null;
                    for (org.springframework.core.io.Resource resource : resources) {
                        if (resource.isReadable()) {
                            metadataReader = metadataReaderFactory.getMetadataReader(resource);
                            try {
                                result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                if (!result.isEmpty()) {
                    HashSet<String> hashResult = new HashSet<>(result);
                    allResult.addAll(hashResult);
                }
            }
            if (!allResult.isEmpty()) {
                typeAliasesPackage = String.join(",",allResult.toArray(new String[0]));
            }
            else {
                String msg = "mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包";
                throw DataException.mybatisException(msg);
            }
        } catch (Throwable t) {
            throw DataException.mybatisException(t.getMessage());
        }
        return typeAliasesPackage;
    }

    public org.springframework.core.io.Resource[] resolveMapperLocations(String[] mapperLocations) {
        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        List<org.springframework.core.io.Resource> resources = new ArrayList<>();
        if (mapperLocations != null) {
            for (String mapperLocation : mapperLocations) {
                try {
                    org.springframework.core.io.Resource[] mappers = resourceResolver.getResources(mapperLocation);
                    resources.addAll(Arrays.asList(mappers));
                }
                catch (IOException e) {
                    // ignore
                }
            }
        }
        return resources.toArray(new org.springframework.core.io.Resource[resources.size()]);
    }
}
